package com.wanwu.channel.service.strategy;

import com.wanwu.channel.common.enums.*;
import com.wanwu.channel.common.exception.SystemException;
import com.wanwu.channel.common.util.DateUtils;
import com.wanwu.channel.converter.PayStatusConvert;
import com.wanwu.channel.core.tool.AlarmPoolUtil;
import com.wanwu.channel.dao.entity.ChannelApplyClearanceEntity;
import com.wanwu.channel.dao.entity.ChannelMerchantInfoEntity;
import com.wanwu.channel.dao.inter.ChannelApplyClearanceDao;
import com.wanwu.channel.dto.vo.PayQueryStrategyReqVo;
import com.wanwu.channel.dto.vo.PayQueryStrategyRespVo;
import com.wanwu.channel.dto.vo.PrepayStrategyReqVo;
import com.wanwu.channel.remote.allinpay.config.TongLianConfig;
import com.wanwu.channel.remote.allinpay.http.TongLianHttp;
import com.wanwu.channel.remote.allinpay.http.TonglianDeclareHttp;
import com.wanwu.channel.remote.allinpay.http.req.TLPrepayReq;
import com.wanwu.channel.remote.allinpay.http.req.TLQueryReq;
import com.wanwu.channel.remote.allinpay.http.resp.DeclareQryRespBody;
import com.wanwu.channel.remote.allinpay.http.resp.TLPrepayResp;
import com.wanwu.channel.remote.allinpay.http.resp.TLQueryResp;
import com.wanwu.channel.service.strategy.domain.CustomsDeclare;
import com.wanwu.channel.service.strategy.domain.PrepayStrategyResponse;
import com.wanwu.channel.tools.DingAlarmTool;
import com.wanwu.monitor.api.util.vo.AlarmMsgVo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @ClassName TongLianPayStrategy
 * @Description 通联支付实现
 * @Author husheng
 * @Date 2020-01-15 15:45
 */
@Component
public class TongLianPayStrategy implements PayStrategy {

    private static final Logger logger = LoggerFactory.getLogger(TongLianPayStrategy.class);
    @Resource
    private TongLianHttp tongLianHttp;
    @Resource
    private TonglianDeclareHttp tonglianDeclareHttp;
    @Resource
    private TongLianConfig tongLianConfig;
    @Resource
    private ChannelApplyClearanceDao channelApplyClearanceDao;
    @Resource
    private DingAlarmTool dingAlarmTool;
    @Resource
    private AlarmPoolUtil alarmPoolUtil;
    @Value("${mq.ding.appKey}")
    private String dingKey;

    /**
     * 统一下单
     *
     * @param payType 传入需要的支付方式
     * @param req     其他额外需要的参数
     * @return
     */
    @Override
    public PrepayStrategyResponse generatePayParams(PayType payType, PrepayStrategyReqVo req) {
        ChannelMerchantInfoEntity entity = req.getChannelMerchantInfoEntity();
        PrepayStrategyResponse response = new PrepayStrategyResponse();
        TLPrepayReq tlPrepayReq = new TLPrepayReq();
        tlPrepayReq.setTrxAmt(req.getPayAmount().toPlainString());
        tlPrepayReq.setReqSn(req.getChannelNo());
        tlPrepayReq.setPayType(convertPayType(payType));
        tlPrepayReq.setBody("万里目商品订单");
        //有效时间固定为10分钟
        tlPrepayReq.setValidTime("10");
        tlPrepayReq.setRemark(req.getAttach());
        tlPrepayReq.setAcct(req.getAcct());
        String notifyUrl = tongLianConfig.getNotifyUrl();
        if (null != entity) {
            notifyUrl = notifyUrl + "/" + entity.getPayChannel() + "/" + entity.getBizCode() + "/" + entity.getMerchantNo();
        }
        tlPrepayReq.setNotifyUrl(notifyUrl);
        //微信有效
        tlPrepayReq.setSubAppId(req.getSubAppId());
        tlPrepayReq.setCusId(req.getCusId());
        tlPrepayReq.setAppId(req.getAppId());
        tlPrepayReq.setChannelMerchantInfoEntity(entity);
        try {
            TLPrepayResp resp = tongLianHttp.prepay(tlPrepayReq);
            //通联交易状态
            response.setTrxStatus(resp.getTrxStatus());
            //记录返回码返回信息
            response.setErrorCode(resp.getTrxStatus());
            response.setErrorMsg(resp.getErrMsg());
            if ("0000".equals(resp.getTrxStatus())) {
                //交易成功
                response.setTradeStatus(TradeStatusEnum.SUCCESS);
                response.setPrepayOrderString(resp.getPayInfo());
                //response.setPid(req.getCusId());
                //response.setAppId(req.getAppId());
                response.setChannelTrxId(resp.getChannelTrxId());
                response.setTrxId(resp.getTrxId());
                response.setPrepayReq(resp.getPrePayReq());
                response.setPrepayResp(resp.getPrePayResp());
            } else {
                //交易失败
                response.setTradeStatus(TradeStatusEnum.FAIL);
                //钉钉告警预下单失败
//                DingUtil.sendDingAtPeople(tongLianConfig.getDingKey(), "通联预下单失败",
//                        "通联预下单失败" + "\n\n业务线单号bizOrderNo：" + req.getBizOrderNo() +
//                                "\n\n商户号：" + req.getCusId() + "\n\n错误码：" + resp.getTrxStatus()
//                                + "\n\n错误信息：" + resp.getErrMsg(), null);
                AlarmMsgVo alarmMsgVo = new AlarmMsgVo.Builder().head("渠道系统告警：通联预下单失败")
                        .field("业务线单号bizOrderNo", req.getBizOrderNo())
                        .field("商户号", req.getCusId())
                        .field("错误码", resp.getTrxStatus())
                        .field("错误信息", resp.getErrMsg()).build();
                alarmPoolUtil.addGatherAlarm(tongLianConfig.getDingKey(), AlarmTypeEnum.TLPREPAYFAIL, alarmMsgVo);

            }
        } catch (Exception e) {
            response.setTradeStatus(TradeStatusEnum.FAIL);
            if (e instanceof SystemException) {
                SystemException ex = (SystemException) e;
                response.setErrorMsg(ex.getMsg());
                response.setErrorCode(ex.getCode());
            } else {
                response.setErrorCode(ExceptionEnum.E10000.name());
                response.setErrorMsg(ExceptionEnum.E10000.getMsg());
            }
        }
        return response;
    }

    /**
     * 通联子渠道转换
     *
     * @param payType
     * @return
     */
    private String convertPayType(PayType payType) {
        switch (payType) {
            case ALLIAN_WECHAT_PAY:
                return "W06";
            case ALLIAN_WECHAT_MINI_PAY:
                return "W06";
            case ALLIAN_ALI_PAY:
                return "A03";
            default:
                return null;
        }
    }

    /**
     * 支付结果查询
     *
     * @param payType
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public PayQueryStrategyRespVo queryPayHttp(PayType payType, PayQueryStrategyReqVo request) {
        PayQueryStrategyRespVo response = new PayQueryStrategyRespVo();
        TLQueryReq req = new TLQueryReq();
        req.setReqSn(0 == request.getThirdFlag() ? request.getBizOrderNo() : request.getChannelNo());
        req.setTrxId(request.getTrxId());
        req.setCusId(request.getMerchantNo());
        req.setAppId(request.getMerchantAppId());
        req.setChannelMerchantInfoEntity(request.getChannelMerchantInfoEntity());
        TLQueryResp resp = tongLianHttp.query(req);
        //返回结果处理
        String trxStatus = resp.getTrxStatus();
        //调用结果成功，如果调用失败，底层已经抛了异常了，这里默认成功
        response.setChannelPayStatus(PayStatusConvert.tonglianConvert(trxStatus));
        response.setAcct(resp.getAcct());

        response.setTlOrderNo(resp.getTrxId());
        response.setThirdOrderNo(resp.getChannelTrxId());

        if ("0000".equals(trxStatus)) {
            //业务结果成功
            response.setFinishTime(DateUtils.formatDate(8, resp.getFinTime()));
            response.setFeeAmount(StringUtils.isEmpty(resp.getFee()) ? "0" : resp.getFee());
        } else if (StringUtils.isEmpty(trxStatus) || "2008".equals(trxStatus) || "2000".equals(trxStatus)) {
            //业务处理中，不需要更新，直接返回处理中
            response.setErrCode(trxStatus);
            response.setErrMsg("通联支付处理中");
        } else {
            //业务结果失败
            response.setErrCode(trxStatus);
            response.setErrMsg(resp.getErrorMsg());
        }
        return response;
    }


    /**
     * 出参转换
     *
     * @param dao
     * @return
     */
    private CustomsDeclare convertResult(ChannelApplyClearanceEntity dao) {
        CustomsDeclare declare = new CustomsDeclare();
        declare.setOutRequestNo(dao.getChannelNo());
        declare.setCustomsPlace(dao.getCustomsPlace());
        declare.setMerchantCustomsNo(dao.getMerchantCustomsNo());
        declare.setMerchantCustomsName(dao.getMerchantCustomsName());
        declare.setAmount(dao.getOrderAmount());
        declare.setIsSplit(dao.getIsSplit());
        declare.setLastModifyTime(dao.getUpdateTime());
        declare.setCustomsCode(dao.getCustomsCode());
        declare.setCustomsInfo(dao.getCustomsInfo());
        declare.setCustomsReturnTime(DateUtils.formatDate(8, dao.getCustomsReturnTime()));
        declare.setVerDept(dao.getVerDept());
        declare.setChannelClearanceStatus(dao.getChannelApplyClearanceStatus().toString());
        return declare;
    }

    /**
     * 通联报关查询结果状态转换为本地状态
     *
     * @return
     */
    private void convertTlStatus(DeclareQryRespBody respBody, ChannelApplyClearanceEntity dao) {
        Integer status;
        TlQryResultEnum customsRet;
        if ("2".equals(respBody.getSendStatus())) {
            //通联发送海关失败
            status = ChannelClearanceStatus.FAIL.getValue();
            customsRet = TlQryResultEnum.DECLARE_FAIL;
        } else if ("0".equals(respBody.getSendStatus())) {
            //通联待发送海关
            status = ChannelClearanceStatus.PROCESSING.getValue();
            customsRet = TlQryResultEnum.NOT_DECLARE;
        } else {
            if ("0".equals(respBody.getInsReceiptStatus())) {
                //电子口岸入库失败
                status = ChannelClearanceStatus.FAIL.getValue();
                customsRet = TlQryResultEnum.TL_INSERT_FAIL;
            } else if ("1".equals(respBody.getInsReceiptStatus())) {
                if ("0".equals(respBody.getCustomsReceiptStatus())) {
                    //海关申报失败
                    status = ChannelClearanceStatus.FAIL.getValue();
                    customsRet = TlQryResultEnum.CUSTOMS_FAIL;
                } else if ("1".equals(respBody.getCustomsReceiptStatus())) {
                    //三单对碰成功认为是成功
                    status = ChannelClearanceStatus.SUCCESS.getValue();
                    customsRet = TlQryResultEnum.SUCCESS;
                } else if ("2".equals(respBody.getCustomsReceiptStatus())) {
                    //申报成功视为处理中，（申报成功指的是还未对碰，属于处理中状态）
                    status = ChannelClearanceStatus.PROCESSING.getValue();
                    customsRet = TlQryResultEnum.NOT_VERIFY;
                } else {
                    //电子口岸入库成功
                    status = ChannelClearanceStatus.PROCESSING.getValue();
                    customsRet = TlQryResultEnum.TL_INSERT_SUCCESS;
                }
            } else {
                //通联发送海关成功
                status = ChannelClearanceStatus.PROCESSING.getValue();
                customsRet = TlQryResultEnum.ALREADY_DECLARE;
            }
        }
        dao.setCustomsReturnTime(respBody.getCustomsReceiptTime());
        dao.setChannelApplyClearanceStatus(status);
        dao.setThirdApplyClearanceStatus(ChannelClearanceStatus.valueOf(status).name());
        dao.setCustomsCode(customsRet.getCode());
        dao.setCustomsInfo(customsRet.getDesc());
        dao.setErrorCode(ExceptionEnum.S00000.name());
        dao.setErrorMsg(ExceptionEnum.S00000.getMsg());
    }


}
